#include "include/global.h"
#include "include/type.h"
#include "include/kconst.h"
#include "include/int.h"
#include "include/init_8259A.h"
#include "include/sysdescriptor.h"
#include "include/klib.h"

extern void sys_call();

typedef void (*func_ptr)();

/* 中断处理函数 */
void	divide_error();
void	single_step_exception();
void	nmi();
void	breakpoint_exception();
void	overflow();
void	bounds_check();
void	inval_opcode();
void	copr_not_available();
void	double_fault();
void	copr_seg_overrun();
void	inval_tss();
void	segment_not_present();
void	stack_exception();
void	general_protection();
void	page_fault();
void	copr_error();
void    hwint00();
void    hwint01();
void    hwint02();
void    hwint03();
void    hwint04();
void    hwint05();
void    hwint06();
void    hwint07();
void    hwint08();
void    hwint09();
void    hwint10();
void    hwint11();
void    hwint12();
void    hwint13();
void    hwint14();
void    hwint15();

func_ptr err_hander_func_ptrs[16] =
{
    divide_error,
    single_step_exception,
    nmi,
    breakpoint_exception,
    overflow,
    bounds_check,
    inval_opcode,
    copr_not_available,
    double_fault,
    copr_seg_overrun,
    inval_tss,
    segment_not_present,
    stack_exception,
    general_protection,
    page_fault,
    copr_error
};
func_ptr hw_int_func_ptrs[16] = 
{
    hwint00,
    hwint01,
    hwint02,
    hwint03,
    hwint04,
    hwint05,
    hwint06,
    hwint07,
    hwint08,
    hwint09,
    hwint10,
    hwint11,
    hwint12,
    hwint13,
    hwint14,
    hwint15
};

char * err_msg[] = 
{
    "#DE Divide Error",
	"#DB RESERVED",
	"--  NMI Interrupt",
	"#BP Breakpoint",
	"#OF Overflow",
	"#BR BOUND Range Exceeded",
	"#UD Invalid Opcode (Undefined Opcode)",
    "#NM Device Not Available (No Math Coprocessor)",
	"#DF Double Fault",
	"Coprocessor Segment Overrun (reserved)",
	"#TS Invalid TSS",
	"#NP Segment Not Present",
	"#SS Stack-Segment Fault",
	"#GP General Protection",
	"#PF Page Fault",
	"--  (Intel reserved. Do not use.)",
	"#MF x87 FPU Floating-Point Error (Math Fault)",
	"#AC Alignment Check",
	"#MC Machine Check",
    "#XF SIMD Floating-Point Exception"
};

void exception_handler(int vec_no,int err_code,int eip,int cs,int eflags)
{
	disp_str("ERROR: ",0x000c000a);
	disp_str(err_msg[vec_no],0x000c0011);
    disp_str("eip:", 0x000c010a);
    disp_u32(eip, 0x000c010e);
}
char buffer[9];
void init_idt_desc(u8 vector, u8 desc_type,
			   int_handler handler, u8 privilege)
{
    GATE *	p_gate	= &idt[vector];
	u32	base	= (u32)handler;
	p_gate->offset_low	= base & 0xFFFF;
	p_gate->selector	= 0x8; /* SELECTOR_KERNEL_CS 段选择子*/
	p_gate->dcount		= 0;
	p_gate->attr		= desc_type | (privilege << 5);
	p_gate->offset_high	= (base >> 16) & 0xFFFF;
}

//初始化idt和8259A中断控制器
void init_idt()
{
    init_8259A();

    // 全部初始化成中断门(没有陷阱门)

    //这里会有问题，一共有16个中断但最后一共中断是16而非15，15是没有的有待后续更该
	for (u8 i = 0; i <= 15; ++i) 
    {
        init_idt_desc(i, DA_386IGate,
		      err_hander_func_ptrs[i], PRIVILEGE_KRNL);
    }
    //为硬件中断设置中断门
    for (u32 i = 32; i <= 47; ++i) 
    {
        init_idt_desc(i, DA_386IGate,
		      hw_int_func_ptrs[i-32], PRIVILEGE_KRNL);
    }
    //设置系统中断号
    init_idt_desc(INT_VECTOR_SYS_CALL, DA_386IGate, sys_call, PRIVILEGE_USER);
    u16* p_idt_limit = (u16*)(&idt_ptr[0]);
	u32* p_idt_base  = (u32*)(&idt_ptr[2]);
	*p_idt_limit = IDT_SIZE * sizeof(GATE) - 1;
	*p_idt_base  = (u32)&idt;
}